/**
 *  Copyright Matt Silbernagel 2010
 *  
 *	This file is part of MobilePrinting.
 *
 *	MobilePrinting is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  MobilePrinting is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with MobilePrinting.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.uc.labs.MobilePrinting.Daemon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;


import edu.uc.labs.MobilePrinting.OSUtils.SanityCheck;
import edu.uc.labs.MobilePrinting.PrintUtils.Printer;
import static edu.uc.labs.MobilePrinting.Configurator.*;

/**
 * @author Matt Silbernagel
 *
 */
public class PrinterProxy extends UnicastRemoteObject implements
		PrinterProxyInterface {

	private static final long serialVersionUID = 1L;

	/**
	 * @throws RemoteException
	 */
	protected PrinterProxy() throws RemoteException {
		super();
	}

	/**
	 * Runs the platform specific command to install the 
	 * printer specified by pName. All other details of 
	 * printer are held in the printer object
	 */
	@Override
	public void add(Printer p, String pName) throws RemoteException {
		LOGGER.debug("Called the remote method add()");
		String line = null;
		@SuppressWarnings("unused")
		String error = null;
		String rValue = null;
		String eValue = null;
		ArrayList<String> cmd = new ArrayList<String>();
		
		if(OS.startsWith("Win")){
			LOGGER.debug("This is windows and the printer isn't already installed");
			// Only install on windows if it currently isn't installed
			cmd.add("rundll32");
			cmd.add("printui.dll,PrintUIEntry");
			cmd.add("/if");
			cmd.add("/b");
			cmd.add(p.getName());
			cmd.add("/f");
			cmd.add(p.getDriver());
			cmd.add("/u");
			cmd.add("/r");
			cmd.add(PORTNAME);
			cmd.add("/m");
			cmd.add("HP Universal Printing PS");
		} else if(OS.startsWith("Mac") || OS.startsWith("Linux")) {
			LOGGER.debug("PrinterManager: It appears you are using Mac OS X or Linux, installing the printer now...");
			cmd.add("/usr/sbin/lpadmin");
			cmd.add("-p");
			cmd.add(pName);
			cmd.add("-o");
			cmd.add("printer-is-shared=false");
			cmd.add("-v");
			cmd.add("lpd://" + p.getServer() + "/" + p.getQueue());
			cmd.add("-L");
			cmd.add(p.getLocation());
			cmd.add("-D");
			cmd.add(pName);
			cmd.add("-P");
			cmd.add(p.getPPD());
			cmd.add("-E");
		}else{
			LOGGER.error("Your OS isn't supported: " + OS );
		}
		
		// Convert the ArrayList to an Array
		String[] command = SanityCheck.listToArray(cmd);
		LOGGER.debug("The command to run for installing the printer: " + SanityCheck.arrayToString(command, " "));
		
		try{
			LOGGER.debug("Installing the printer...");
			Process process = Runtime.getRuntime().exec(command);
			
			// Get the output and error streams
			BufferedReader output = new BufferedReader(new InputStreamReader(process
					.getInputStream()));
			@SuppressWarnings("unused")
			BufferedReader errput = new BufferedReader(new InputStreamReader(process
					.getErrorStream()));
			
			// Read the output
			while ((line = output.readLine()) != null) {
				rValue += line;
			}
			
			// Read the errors
			while ((error = output.readLine()) != null){
				eValue += line;
			}
		}catch (IOException e){
			LOGGER.error("Error installing printer: " + e.toString());	
		}
		
		if (eValue != null){
			LOGGER.error("Command returned an error: \n\t" + eValue );
		}
		
		if (rValue != null){
			LOGGER.debug("The install command returned something on the standard output: \n\t" +
					rValue + "\n\n");
		}

	}
	
	@Override
	public boolean addPort(Printer p) throws RemoteException {
		LOGGER.debug("Called the remote method addPort()");
		return false;
	}

	/**
	 * Runs the platform specific command to remove the 
	 * printer specified by pName. 
	 */
	@Override
	public String remove(String pName) throws RemoteException {
		LOGGER.debug("Called the remote method remove()");
		ArrayList<String> cmd = new ArrayList<String>();
		String line = null;
		String error = null;
		String returnVal = null;
		
		if (OS.startsWith("Win")) {
			cmd.add("cscript.exe");
			cmd.add(WINSCRIPTSPATH + "\\prnmngr.vbs");
			cmd.add("-d");
			cmd.add("-p");
			cmd.add(pName);
		} else if(OS.startsWith("Mac") || OS.startsWith("Linux")) {
			cmd.add("lpadmin");
			cmd.add("-x");
			cmd.add(pName);
		}
		
		// Convert ArrayList to Array
		//String command[] = (String[]) cmd.toArray();
		String[] command = SanityCheck.listToArray(cmd);	
		try {
			LOGGER.debug("Removing printer " + pName);
			LOGGER.debug("Using the command " + SanityCheck.arrayToString(command, " "));
			Process process = Runtime.getRuntime().exec(command);	
			
			// Get the output and error streams
			BufferedReader output = new BufferedReader(new InputStreamReader( process.getInputStream()));
			BufferedReader errput = new BufferedReader(new InputStreamReader( process.getErrorStream()));	
			
			LOGGER.debug("Here is the standard output of the remove printer command:\n");			 
			while ((line = output.readLine()) != null) {		
				//LOGGER.debug(line);
				returnVal += line;
			}
			
			if(returnVal != null)
				return returnVal;
			
			LOGGER.debug("Here is the standard error of the remove printer command:\n");
			while ((error = errput.readLine()) != null) {
				LOGGER.error(error);
				returnVal += line;
			}			
		
			if(returnVal != null)
				return returnVal;
			
			
		} catch (IOException e){
			return e.toString();
		}
		
		return "none";
		
	}
	
	
}
